#include "./themedraw.h"

ThemeDraw::ThemeDraw()
{
}

ThemeDraw::~ThemeDraw()
{

}

void* ThemeDraw::PaintButton(int width, int height)
{
    RECT rc = {0, 0, width, height};
    HANDLE handle = ::OpenThemeData(NULL, L"Button");

    CacheBitmap bitmap = CreateBitmap(width, height);
    ::DrawThemeBackground(handle, bitmap.hDC, BP_PUSHBUTTON, PBS_DEFAULTED, &rc, NULL);

    bitmap.buf = UpSideDown(bitmap, !!::IsThemeBackgroundPartiallyTransparent(handle, BP_PUSHBUTTON, PBS_DEFAULTED));
    ::DeleteDC(bitmap.hDC);
    ::DeleteObject(bitmap.hBitmap);

    return bitmap.buf;
}

void* ThemeDraw::PaintRadio(int width, int height)
{
    RECT rc = {0, 0, width, height};
    HANDLE handle = ::OpenThemeData(NULL, L"Button");

    CacheBitmap bitmap = CreateBitmap(width, height);
    ::DrawThemeBackground(handle, bitmap.hDC, BP_RADIOBUTTON, PBS_DEFAULTED, &rc, NULL);

    bitmap.buf = UpSideDown(bitmap, !!::IsThemeBackgroundPartiallyTransparent(handle, BP_RADIOBUTTON, PBS_DEFAULTED));
    ::DeleteDC(bitmap.hDC);
    ::DeleteObject(bitmap.hBitmap);

    return bitmap.buf;
}

void* ThemeDraw::PaintCheckbox(int width, int height)
{
    RECT rc = {0, 0, width, height};
    HANDLE handle = ::OpenThemeData(NULL, L"Button");

    CacheBitmap bitmap = CreateBitmap(width, height);
    ::DrawThemeBackground(handle, bitmap.hDC, BP_CHECKBOX, PBS_DEFAULTED, &rc, NULL);

    bitmap.buf = UpSideDown(bitmap, !!::IsThemeBackgroundPartiallyTransparent(handle, BP_CHECKBOX, PBS_DEFAULTED));
    ::DeleteDC(bitmap.hDC);
    ::DeleteObject(bitmap.hBitmap);

    return bitmap.buf;
}

void* ThemeDraw::PaintScrollBar(int width, int height)
{
    RECT rc = {0, 0, width, height};
    HANDLE handle = ::OpenThemeData(NULL, L"ScrollBar");

    CacheBitmap bitmap = CreateBitmap(width, height);
    ::DrawThemeBackground(handle, bitmap.hDC, SBP_LOWERTRACKHORZ, SCRBS_NORMAL, &rc, NULL);

    RECT rcThumb = {height + 20, 0, height + 60, height};
    ::DrawThemeBackground(handle, bitmap.hDC, SBP_THUMBBTNHORZ, SCRBS_NORMAL, &rcThumb, NULL);

    RECT rcArrowLeft = {0, 0, height, height};
    ::DrawThemeBackground(handle, bitmap.hDC, SBP_ARROWBTN, ABS_LEFTHOVER, &rcArrowLeft, NULL);

    RECT rcArrowRight = {width - height, 0, width, height};
    ::DrawThemeBackground(handle, bitmap.hDC, SBP_ARROWBTN, ABS_RIGHTHOVER, &rcArrowRight, NULL);

    bitmap.buf = UpSideDown(bitmap, !!::IsThemeBackgroundPartiallyTransparent(handle, SBP_LOWERTRACKHORZ, SCRBS_NORMAL));
    ::DeleteDC(bitmap.hDC);
    ::DeleteObject(bitmap.hBitmap);

    return bitmap.buf;
}

ThemeDraw::CacheBitmap ThemeDraw::CreateBitmap(int width, int height)
{
    HDC hDC = ::CreateCompatibleDC(NULL);
    ::SetGraphicsMode(hDC, GM_ADVANCED);
    ::SetBkMode(hDC, TRANSPARENT);

    BITMAPINFO info = {0};
    info.bmiHeader.biSize = sizeof(info.bmiHeader);
    info.bmiHeader.biWidth = width;
    info.bmiHeader.biHeight = height;
    info.bmiHeader.biPlanes = 1;
    info.bmiHeader.biBitCount = 32;
    info.bmiHeader.biCompression = BI_RGB;
    HBITMAP hBitmap;
    void* bits;
    hBitmap = ::CreateDIBSection(hDC, &info, DIB_RGB_COLORS, &bits, 0, 0);
    ::SelectObject(hDC, hBitmap);

    memset(bits, 0x00, width * height * 4);

    CacheBitmap bitmap;
    bitmap.width = width;
    bitmap.height = height;
    bitmap.hDC = hDC;
    bitmap.hBitmap = hBitmap;
    bitmap.buf = bits;

    return bitmap;
}

void* ThemeDraw::UpSideDown(ThemeDraw::CacheBitmap bitmap, bool alphaBlend)
{
    unsigned int* dstBits = new unsigned int[bitmap.width * bitmap.height];
    unsigned int* dst = dstBits + bitmap.width * (bitmap.height - 1);
    unsigned int* src = (unsigned int*)bitmap.buf;

    for (int y = 0; y < bitmap.height; ++y)
    {
        for (int i = 0; i < bitmap.width; ++i)
        {
            dst[i] = src[i];
            if (!alphaBlend)
                dst[i] |= 0xff000000;
        }
        src += bitmap.width;
        dst -= bitmap.width;
    }
    return dstBits;
}